﻿using System;
using System.Collections.Generic;

namespace PT.NoteDetection.Util {
    public class CircularArrayQueue<T> : IEnumerable<T> {

        readonly T[] s;
        int ai, ri;

        public CircularArrayQueue(int capacity) {
            s = new T[capacity];

            Count = ai = ri = 0;
        }

        public int Count { get; private set; }
        public int Capacity { get { return s.Length; } }

        public bool IsFull { get { return Count == s.Length; } }
        public bool IsEmpty { get { return Count == 0; } }

        public void Add(T sample) {
            if (IsFull) {
                Remove();
            }

            s[ai] = sample;

            ++ai;
            ai %= s.Length;
            ++Count;
        }

        public void Remove() {
            if (IsEmpty) {
                throw new InvalidOperationException("Collection is empty.");
            }

            ++ri;
            ri %= s.Length;
            --Count;
        }

        public T this[int index] { 
            get {
                if (index < 0 || Count <= index) {
                    throw new ArgumentOutOfRangeException("index");
                }

                return s[(ri + index) % s.Length];
            } 
        }

        #region IEnumerable<T> Members

        public IEnumerator<T> GetEnumerator() {
            for (int i = ri; i < Count; ++i) {
                yield return s[i % s.Length];
            }

            yield break;
        }

        #endregion

        #region IEnumerable Members

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
            return GetEnumerator();
        }

        #endregion
    }
}
